package com.ican.javadoc.common.common;

import java.io.ByteArrayOutputStream;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.stream.StreamResult;

import org.springframework.oxm.Marshaller;
import org.springframework.util.FileCopyUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.servlet.view.AbstractView;

public class XmlMarshallingView extends AbstractView {
 
    public static final String DEFAULT_CONTENT_TYPE = "application/xml";

    private Marshaller marshaller;

    public XmlMarshallingView() {
        setContentType(DEFAULT_CONTENT_TYPE);
        setExposePathVariables(false);
    }

    public XmlMarshallingView(Marshaller marshaller) {
        setContentType(DEFAULT_CONTENT_TYPE);
        this.marshaller = marshaller;
        setExposePathVariables(false);
    }

    public void setMarshaller(Marshaller marshaller) {
        this.marshaller = marshaller;
    }

    @Override
    protected void renderMergedOutputModel(Map<String, Object> model, 
                                           HttpServletRequest request, 
                                           HttpServletResponse response) throws Exception {
        Object toBeMarshalled = locateToBeMarshalled(model);
        if (toBeMarshalled == null) {
            throw new ServletException("Unable to locate object to be marshalled in model: " + model);
        }
        ByteArrayOutputStream bos = new ByteArrayOutputStream(2048);
        marshaller.marshal(toBeMarshalled, new StreamResult(bos));

        response.setContentType(getContentType());
        response.setContentLength(bos.size());

        FileCopyUtils.copy(bos.toByteArray(), response.getOutputStream());
    }

    protected Object locateToBeMarshalled(Map<String, Object> model) throws ServletException {
        if(model != null){
            for (Object o : model.values()) {
                //解决对象添加到ModelAndView中，转换后的xml是BindingResult信息的bug
                if (o instanceof BindingResult) {
                    continue;
                }
                if (this.marshaller.supports(o.getClass())) {
                    return o;
                }
            }
        }
        return null;
    }        
}
